﻿using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using PMS.SANY.MonOrderServer.Enums;
using PMS.SANY.MonOrderServer.Siemens;
using S7.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PMS.SANY.MonOrderServer
{
    /// <summary>
    /// 生产工位
    /// </summary>
    public partial class WorkStation
    {
        public ILogger<Worker> _logger;

        public Worker Parent { set; get; }

        /// <summary>
        /// 工位编码
        /// </summary>
        public string Id { set; get; }

        /// <summary>
        /// 可替补的工位编码
        /// </summary>
        public List<string> AlternateId { set; get; }

        /// <summary>
        /// 工位名称
        /// </summary>
        public string Name { set; get; }

        /// <summary>
        /// 工序号
        /// </summary>
        public string OprSequenceNo { set; get; }

        /// <summary>
        /// 前工序号
        /// </summary>
        public string PreOprSequenceNo { set; get; }

        public string[] SerialNo { set; get; }

        /// <summary>
        /// 工位当前工作状态
        /// </summary>
        public WorkStationStatus Status { private set; get; }

        /// <summary>
        /// 调度是否执行
        /// </summary>
        public bool IsRunning { private set; get; }

        /// <summary>
        /// 检测进度
        /// </summary>
        public bool IsChecking { private set; get; }

        /// <summary>
        /// 检测进度
        /// </summary>
        public bool IsStartChecking { private set; get; }

        private List<string> sid { set; get; }

        public bool IsLastSeq { private set; get; }

        private WorkStation()
        {
            IsLastSeq = false;
        }

        public WorkStation(SiemensHelper siemens,bool isLastSeq = false)
        {
            Siemens = siemens;
            Status = WorkStationStatus.Free;
            IsChecking = false;
            IsLastSeq = isLastSeq;
        }

        /// <summary>
        /// 开始运行
        /// </summary>
        /// <param name="delay">轮询间隔时间，单位秒</param>
        /// <returns></returns>
        public async Task StartRunningAsync(int delay = 30)
        {
            //保证一个实例只启用一个Running方法
            if (IsRunning) return;
            else IsRunning = true;

            Siemens.Regist(Ip, StartUpAddress.Address);
            Siemens.Regist(Ip, CompleteAddress.Address);

            if (!string.IsNullOrWhiteSpace(EnabledAddress.Address))
                Siemens.Regist(Ip, EnabledAddress.Address);

            while (IsRunning)
            {
                try
                {
                    switch (Status)
                    {
                        case WorkStationStatus.Unabled:
                            if (!CheckDisabled())
                            {
                                _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】恢复启用，可向其下发新订单。");
                                Status = WorkStationStatus.Free;
                            }
                            break;
                        case WorkStationStatus.Free://空闲状态
                            if (!CheckDisabled())
                            {
                                await LoadingOrderAsync();//尝试获取待生产的订单
                            }
                            else
                            {
                                Status = WorkStationStatus.Unabled;
                                _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】停用，不接收订单。");
                            }
                            break;
                        case WorkStationStatus.IsIssued://下发状态
                            if (await PreSequenceCompnayAsync(WipOrderNo))
                            {
                                await IssuedOrderAsync();//下发订单至PLC
                            }
                            else
                            {
                                _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>订单【" + WipOrderNo + "】因上工序【" + PreOprSequenceNo + "】未完成，暂不下发至工位【" + Name + "】。");
                            }
                            break;
                        case WorkStationStatus.WaitingToStart:
                            _ = CheckStartAsync();        //等待开工信号
                            break;
                        case WorkStationStatus.InProduction:
                            _ = CheckStatusAsync();     //执行状态开始向PLC读取状态数据
                            break;
                        case WorkStationStatus.Completed://订单完成
                            await CheckPlanStatusAsync(WipOrderNo);
                            await ClearOrderAsync();//清理生产工位数据
                            break;
                    }

                    _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "==>" + Id + "】 状态【" + StatusName() + "】");
                }
                catch (Exception ex)
                {
                    _logger.LogError("StartRunningAsync:" + ex.Message);
                }

                await Task.Delay(1000 * DelaySeconds());
            }
        }

        private int DelaySeconds()
        {
            var result = 30;
            switch (Status)
            {
                case WorkStationStatus.Free://空闲状态
                    result = 60;
                    break;
                case WorkStationStatus.IsIssued://下发状态
                    result = 30;
                    break;
                case WorkStationStatus.WaitingToStart:
                    result = 1;
                    break;
                case WorkStationStatus.InProduction:
                    result = 30;
                    break;
                case WorkStationStatus.Completed://订单完成
                    result = 10;
                    break;
            }
            return result;
        }

        private string StatusName()
        {
            var result = "";
            switch (Status)
            {
                case WorkStationStatus.Free://空闲状态
                    result = "空闲";
                    break;
                case WorkStationStatus.IsIssued://下发状态
                    result = "下发任务至PLC";
                    break;
                case WorkStationStatus.WaitingToStart:
                    result = "等待开工";
                    break;
                case WorkStationStatus.InProduction:
                    result = "生产中";
                    break;
                case WorkStationStatus.Completed://订单完成
                    result = "完工";
                    break;
                case WorkStationStatus.Unabled://订单完成
                    result = "不可用";
                    break;

            }
            return result;
        }

        private bool CheckDisabled()
        {
            if (!string.IsNullOrWhiteSpace(EnabledAddress.Address))
            {
                return Siemens.Read(Ip, EnabledAddress.Address);
            }
            else
            {
                return true;
            }
        }

        private async Task CheckStartAsync(int delay = 1)
        {
            if (IsStartChecking) return;
            else IsStartChecking = true;

            _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】订单【" + WipOrderNo + "】等待开工信号。");
            bool isStart = false;
            while (IsStartChecking)
            {
                try
                {
                    if (AlternateId != null && AlternateId.Count > 0)
                    {
                        var disabled = Siemens.Read(Ip, EnabledAddress.Address);
                        if (disabled)
                        {//当前工位不可用
                            if (Status == WorkStationStatus.IsIssued || Status == WorkStationStatus.WaitingToStart
                                || Status == WorkStationStatus.InProduction)
                            {
                                await ModifySequenceAsync(OprSequenceId, "120");
                                await ModifyParam4Async(OprSequenceId, "");
                                await ClearOrderAsync();//清理生产工位数据
                            }

                            Status = WorkStationStatus.Unabled;
                            IsChecking = false;
                            _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】为不可用状态，不能进行开工操作。");
                            return;
                        }
                    }

                    var value = Siemens.Read(Ip, StartUpAddress.Address);
                    if (isStart != value)
                    {
                        isStart = value;
                        if (isStart)
                        {
                            _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】订单【" + WipOrderNo + "】收到开工信号。");
                            //报开工信号
                            await ModifySequenceAsync(OprSequenceId, "130");
                            Status = WorkStationStatus.InProduction;

                            #region --向MON报开工--
                            await MonReportAsync("0");
                            #endregion
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(" 【" + WipOrderNo + "】 CheckStartAsync=" + ex.Message);
                }

                await Task.Delay(1000 * delay);
            }

            IsStartChecking = false;
        }

        private async Task CheckStatusAsync(int delay = 1)
        {
            if (IsChecking) return;
            else IsChecking = true;

            bool isCompleted = false;

            _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】订单【" + WipOrderNo + "】等待完工信号。");
            while (IsChecking)
            {
                try
                {
                    if (AlternateId != null && AlternateId.Count > 0)
                    {
                        var disabled = Siemens.Read(Ip, EnabledAddress.Address);
                        if (disabled)
                        {//当前工位不可用
                            if (Status == WorkStationStatus.IsIssued || Status == WorkStationStatus.WaitingToStart
                                || Status == WorkStationStatus.InProduction)
                            {
                                await ModifySequenceAsync(OprSequenceId, "120");
                                await ModifyParam4Async(OprSequenceId, "");
                                await ClearOrderAsync();//清理生产工位数据
                            }

                            Status = WorkStationStatus.Unabled;
                            IsChecking = false;
                            _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】为不可用状态，不能进行报完工操作。");
                            return;
                        }
                    }

                    var value = Siemens.Read(Ip, CompleteAddress.Address);
                    if (isCompleted != value)
                    {
                        isCompleted = value;
                        if (isCompleted)
                        {
                            _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】订单【" + WipOrderNo + "】收到完工信号。");
                            ActQuantity += 1;
                            if (ActQuantity >= Quantity)
                            {
                                await ModifySequenceAsync(OprSequenceId, "140");
                            }
                            else
                            {
                                await ModifySequenceAsync(OprSequenceId, "130");
                            }

                            #region --向MON报工--
                            await MonReportAsync("1");
                            #endregion

                            if (ActQuantity >= Quantity) Status = WorkStationStatus.Completed;
                            else Status = WorkStationStatus.InProduction;
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(" CheckStatusAsync=" + ex.Message);
                }

                await Task.Delay(1000 * delay);
            }

            IsChecking = false;
        }

        /// <summary>
        /// 获取待生产的订单
        /// </summary>
        /// <returns></returns>
        private async Task LoadingOrderAsync()
        {
            Status = WorkStationStatus.Loading;
            var seq = await GetNextSequenceAsync();
            if (seq == null)
            {//当前未能获取到
                _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】没有匹配到新订单。");
                Status = WorkStationStatus.Free;
            }
        }

        /// <summary>
        /// 下发订单至PLC
        /// </summary>
        /// <returns></returns>
        private async Task IssuedOrderAsync()
        {
            var result = await IssuedToPlcAsync(3);
            if (result)
            {//下发成功，待开工
                _logger.LogInformation("==[" + DateTime.Now.ToString("HH:mm:ss") + "]==>工位【" + Name + "】下发订单成功【" + WipOrderNo + "】。");
                await ModifySequenceAsync(OprSequenceId, "125");

                Status = WorkStationStatus.WaitingToStart;
            }
        }

        /// <summary>
        /// 清理工位订单信息
        /// </summary>
        /// <returns></returns>
        private async Task ClearOrderAsync()
        {
            await Task.Delay(1000 * 15);

            IsChecking = false;
            OprSequenceId = "";
            WipOrderNo = "";
            //OprSequenceNo = "";
            Quantity = 0;
            ActQuantity = 0;
            Status = WorkStationStatus.Free;

            await IssuedToPlcAsync(3);
        }
    }
}
